<template>
    <article class="cmp cmp-decode-single">
        <section class="content-wrapper">
            <div :class="['content-left', ocrType]">
                <img v-if="imgUrl" :src="imgUrl" ref="imgObj" />
                <div v-else class="nodata">将图片拖拽或粘贴到此处</div>
                <div class="mask" @drop.prevent="filesDrop" @dragover.prevent @paste.stop="pasteHandler"></div>
            </div>
            <div class="content-right">
                <textarea v-model="content" placeholder="识别结果" readonly></textarea>
            </div>
        </section>
        <section class="btn-wrapper">
            <x-button type="primary" block @click="decode" :loading="loadingCount > 0">识 别</x-button>
        </section>
    </article>
</template>

<script>
import { createWorker } from 'tesseract.js'
let paddleOCR = global.require('@paddlejs-models/ocr')
export default {
    name: 'cmp-decode-single',
    props: {
        AccessToken: {type: String, default: ''},
        ocrType: {type: String, default: 'baiduapi'}
    },
    data() {
        return {
            file: '',
            imgUrl: '',
            content: '',
            loadingCount: 0
        }
    },
    methods: {
        // 拖拽待处理文件
        filesDrop(e) {
            const filesList = e.dataTransfer.files
            if (!filesList) return
            this.file = filesList[0]
            this.content = ''
            this.imgUrl = ''
            this.$jstools.File2dataUrl(this.file).then(res => {
                this.imgUrl = res
            })
        },
        // 粘贴图片
        pasteHandler(e) {
            let items = (e.clipboardData || {}).items
            if (!items) return
            for (let i = 0; i < items.length; i++) {
                let item = items[i]
                if (item.kind === 'file' && /^image\//.test(item.type)) {
                    let file = item.getAsFile()
                    if (file.size > 0) {
                        this.file = file
                        this.content = ''
                        this.imgUrl = ''
                        this.$jstools.File2dataUrl(this.file).then(res => {
                            this.imgUrl = res
                        })
                        break
                    }
                }
            }
        },
        // 识别
        decode() {
            if (!this.imgUrl) {
                return this.$toast('请选择要识别的图片')
            }
            this.content = ''
            if (this.ocrType === 'baiduapi') {
                this.decodeByBaidu()
            } else if (this.ocrType === 'paddle') {
                this.decodeByPaddle()
            } else if (this.ocrType === 'tesseract') {
                this.decodeByTesseract()
            }
        },
        // Tesseract
        decodeByTesseract() {
            if (!this.imgUrl) {
                return this.$toast('请选择要识别的图片')
            }
            this.loadingCount++
            this.$nextTick(async () => {
                const worker = await createWorker(['eng', 'chi_sim'])
                const res = await worker.recognize(this.imgUrl)
                this.content = ((res || {}).data || {}).text || ''
                await worker.terminate()
                this.loadingCount--
                this.$toast('执行完毕')
            })
        },
        // 飞桨
        decodeByPaddle() {
            if (!this.$refs.imgObj) {
                return this.$toast('请选择要识别的图片')
            }
            this.loadingCount++
            this.$nextTick(async () => {
                await paddleOCR.init()
                paddleOCR.recognize(this.$refs.imgObj).then(res => {
                    this.content = (res.text || []).join('\n')
                }).finally(() => {
                    this.loadingCount--
                    this.$toast('执行完毕')
                })
            })
        },
        // 百度在线API
        decodeByBaidu() {
            if (!this.AccessToken) {
                return this.$toast('请先获取AccessToken后再试')
            }
            this.loadingCount++
            let formData = new FormData()
            formData.append('image', this.imgUrl)
            this.$jstools.ajax({
                method: 'post',
                url: `https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token=${this.AccessToken}`,
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Accept': 'application/json'
                },
                data: formData
            }).then((res) => {
                let words_result = ((res || {}).data || {}).words_result || []
                this.content = words_result.map(v => v.words).join('\n')
            }).catch((err) => {
                console.log(err)
            }).finally(() => {
                this.loadingCount--
                this.$toast('执行完毕')
            })
        },
    }
}
</script>

<style scoped lang="less">
@import "~@/assets/css/_mixins.less";
@import "~@/assets/css/_color.less";

.cmp-decode-single {
    height: calc(100% - 3em - 64px);
    display: flex;
    flex-direction: column;
    justify-content: space-between;

    .content-wrapper {
        height: 0;
        flex-grow: 1;
        display: flex;
        .content-left,
        .content-right {
            width: 50%;
            border: 1px solid #e6e6e6;
            background-color: #fff;
        }

        .content-left {
            height: 100%;
            border-radius: .5em;
            overflow: auto;
            position: relative;
            img {
                width: 100%;
                height: auto;
            }
            .nodata {
                border-radius: .5em;
            }
            .mask {
                .absolute-fullscreen;
                z-index: 2;
            }
        }

        .content-right {
            margin-left: 1em;
            border-radius: .5em;
            position: relative;
            overflow: hidden;
        }

        textarea {
            width: 100%;
            height: 100%;
            font-size: 16px;
            padding: 18px 24px;
            border: none;
            outline: 0;
            resize: none;
        }
    }

    .btn-wrapper {
        margin-top: 1em;
    }
}
</style>
